
const EventEmitter = require("events").EventEmitter
const WebSocket = require("websocket").client
const Moment = require("moment")

const cli = new WebSocket() 
let ws = null 

const Read = process.stdin , 
    Write = process.stderr 

Read.setRawMode( true )

let inputBuff = []
let inputIndex = 0 
let showIndex = 0 
const downIndex = Write.rows - 1 

class KeyEventEmitter extends EventEmitter{

    constructor(){
        super()
    }

}

const Events = new KeyEventEmitter()

function clearLine( row , idx , cb ){

    Write.cursorTo( idx || 0  , row , () => { 
        //判断是否为字符
        Write.clearLine( 1 , cb )
    })

}

function clearScreen( startRow , startIdx , cb ) {
    Write.cursorTo( startIdx || 0 , startRow , () => {
        Write.clearScreenDown( cb )
    })
}


function writeLine( row , idx , data , cb ){
    clearLine( row , idx , () => {
        Write.cursorTo( idx , row , () => {
            Write.write( data , cb )
        } )
    })
}

function isChn( c ){
    const re=/[^\u4e00-\u9fa5]/ ;
    if (re.test( c  )) return false ;
    return true
}


Events.on("backspace" , () =>{

    const last = inputBuff.pop()
    if( !last) return 

    const lastStr = last.toString()
    const lastStrLen = lastStr.length 
    const lastChar = lastStr[ lastStrLen - 1 ]

    if( isChn( lastChar) ){
        showIndex -= 2 
        inputIndex -= 3 
    }else{
        showIndex -= 1 
        inputIndex -= 1 
    }

    if( lastStrLen > 1 ){
        const newStr = lastStr.substring( 0 , lastStrLen -1 )
        inputBuff.push( Buffer.from(newStr))
    }

    //TODO 可以获取当前光标的位置，从当前光标处删除
    Write.cursorTo( showIndex  , downIndex , () => { 
        //判断是否为字符
        Write.clearLine( 1 )
    })

})

Read.on("data" , ( data ) => {
    //ctrl + c 
    if( data[0] == 3 ) process.exit(0)

    if( data[0] == 127 ){
        //backspace
        Events.emit("backspace")
        return 
    }

    if( data[0] == 13 ){
        //enter
        clearLine( downIndex , 0 , () => {
            if( inputIndex == 0 ) return 
            Events.emit( "enter" , Buffer.concat( inputBuff , inputIndex ) )
            inputBuff = []
            inputIndex = 0 
            showIndex = 0 
        })
        return 
    }

    //默认最后一行输入显示
    Write.cursorTo( showIndex , downIndex  , () => {

        Write.write( data , ()=>{})
        const str = data.toString()
        const strLen = str.length 
        for( let idx = 0 ; idx < strLen ; idx ++ ){
            const s = str[ idx ]
            if( isChn(s) ){
                showIndex += 2 
                inputIndex += 3 
            }else{
                inputIndex += 1 
                showIndex += 1 
            }

        }
    })

    inputBuff.push( data )

})

let lastTime = Date.now

Events.on("enter" , ( buff ) => {
    const now = Date.now 
    if( (lastTime + 500 ) < now ){
        return 
    }
    // writeLine( 2 , 0 , buff )
    // const str = buff.toString()
    // const now = Moment().format("YYYY-MM-DD HH:mm:ss")
    // const fmtMsg = `${now} Me : \t${str}`
    // addData( fmtMsg )
    lastTime = Date.now 
    ws.send( buff.toString() )
    // console.log( buff )
    // writeLine( 3 , 0 ,  buff )
})


Write.on("resize" , ()=>{
    // maxRow = ( Write.rows - startRow - 3 )
})

const startRow = 5 ,
    maxRow = ( Write.rows - startRow - 3 )

let curIndex  = 0  ,
    rows = new Array(10)

let tempData = []

function addData( buff ){
    if( typeof( buff) == "string")
        buff = Buffer.from( buff )
    tempData.push( buff )
}

function readData(){
    setTimeout( ()=> {
        const tmp = tempData.pop()
        if( tmp && tmp.length > 0  )
            addData2( tmp )
        readData()
    } , 200 )
}

readData()

function addData2( buff  ){

    const rowLen = rows.length 
    if( curIndex >= maxRow ){
        curIndex = 0 
    }

    rows[ curIndex ] = buff 
    // if( rowLen == maxRow ){

    // }else{
    //     rows.push( buff )
    // }
    curIndex ++ 
    // showData2()
}

function makeSpace( dataLen ) {
    const len = Write.columns - 1 
    let out = ""
    for( ; dataLen < len ; dataLen ++ ){
        out += " "
    }
    return out 
}

function showData2(){
    
    // if( lastIndex == curIndex ){
    //     setTimeout( showData2  , 1000 )
    //     return 
    // }else{
    //     lastIndex = curIndex 
    // }

    const copyData = rows
    let copyIndex = curIndex 
    let output = ""
    for( let count = 0 ; count < maxRow ; count ++ ){
        
        if( copyIndex >= maxRow ){
            copyIndex = 0 
        }
        let idx = copyIndex 
        const data = copyData[ idx] || ""
        
        let dataLen = data.length
        let val = dataLen%Write.columns 
        dataLen = val > 1 ? val : dataLen
        if( val > 1 ){
            count = Math.floor( count + ( dataLen / Write.columns ) )
        }
        // console.log(`${count} ${val} ${data}`)
        output += data  + makeSpace( dataLen + 5) + "\n"

        copyIndex ++ 

    }
    // console.log( `${startRow} - ${output}` )
    //         setTimeout( showData2 , 1500 )
    writeLine( startRow , 0 , `${output}`  , () => {
        Write.cursorTo( showIndex , downIndex , () => {
            setTimeout( showData2 , 1500 )
        })
    })
}


function connected( conn ){
    ws = conn 
    clearScreen( 0 , 0 , () => {
        writeLine(0 , 0 , `Welcome to chat. Connected:${ws.remoteAddress} ${ws.state}  Window: ${Write.rows} x ${Write.columns}` , () => {
            Write.cursorTo( showIndex , downIndex )
        })
    })
    showData2()
}

cli.on("connectFailed" , function( err ){
    console.log( err )
})

cli.on("connect" , function( conn ){
    // console.log( conn )
    connected( conn )
    conn.on("message" , function( msg ) {
        if( msg.type == "utf8"){
            const now = Moment().format("YYYY-MM-DD HH:mm:ss")
            // console.log( msg.utf8Data )
            addData( `${now} \t${msg.utf8Data}` )
        }
    })
    // console.log( cli )
    // conn.sendUTF("aaa")
})

cli.connect("ws://172.16.2.119:9002" )

